#!/usr/bin/env python

import sys
import logging
import logging.config
import time
import os
import asterisk.manager
import ConfigParser
import MySQLdb

from astpychannel import Channel 
from astpydb import PersistData 
from astpyhandlers import handle_agentlogin_event, handle_agentlogoff_event, handle_agents_event, handle_dial_event, handle_hangup_event, handle_link_event, handle_peerentry_event, handle_peerstatus_event 

def asteriskConnect(manager, host, port, user, password):
	""" Connects to the asterisk manager """
	try:
		manager.connect(host, port)
		manager.login(user, password)
		logging.info("Connected to asterisk manager %s" % host)
		return 1
	except asterisk.manager.ManagerSocketException, (errno, reason):
		logging.error(reason)
		return 0
	except asterisk.manager.ManagerAuthException, reason:
		# this is a critical exception
		logging.critical("Authentication problem: %s" % reason)
		print reason
		sys.exit(0)
	except asterisk.manager.ManagerException, reason:
		logging.error(reason)
		return 0

def main():
	astpyconfig = "conf/astpy.conf"
	loggingconfig = "conf/logging.conf"

	# specify logging config file
	logging.config.fileConfig(loggingconfig)
	# read config file
	logging.info("Initializing [astpy]")

	config = ConfigParser.ConfigParser()
	config.read(astpyconfig)
	try:
		# asterisk manager config parameters
		host = config.get("asterisk-manager", "host")
		port = config.get("asterisk-manager", "port")
		username = config.get("asterisk-manager", "username")
		password = config.get("asterisk-manager", "password")
		daemon = config.get("general", "daemon")
		
		# output database config parameters
		dbhost = config.get("database", "dbhost")
		dbuser = config.get("database", "dbuser")
		dbpass = config.get("database", "dbpass")
		dbname = config.get("database", "dbname")
		dbretries = int(config.get("database", "dbretries"))
	except ConfigParser.NoOptionError, reason:
		# if there is a parameter missing, we can continue.
		logging.critical("On file %(conffile)s: %(reason)s" % {"conffile": astpyconfig, "reason": reason} )
		sys.exit(1)

	try:
		# connect to the asterisk database.
		db = PersistData(dbhost, dbuser, dbpass, dbname, dbretries)
	except MySQLdb.OperationalError, reason:
		logging.critical("MySQLdb: %s" % reason)
		print "MySQLdb: %s" % reason	
		sys.exit(1)

	retries = 0
	manager = asterisk.manager.Manager()
	try:
		if daemon == "1":
			# fork (daemon=1)
			logging.info("Forking..")
			pid = os.fork()
		else:
			# dont fork (daemon=0)
			pid = 0
		if (pid == 0):
			while 1:
				if manager.connected():
					# Wait 5 seconds and check connection status again
					time.sleep(5)
				else:
					manager.close()
					manager = asterisk.manager.Manager()
					retries = retries + 1
					if retries > 1:
						time.sleep(retries * 2)
					logging.info("Connecting to the Asterisk manager")
					if asteriskConnect(manager, host, port, username, password):
						# register events
						retries = 0
						logging.info("Registering Asterisk manager events")
						
						# Call status events
						manager.register_event("Link", handle_link_event)
						manager.register_event("Dial", handle_dial_event)
						manager.register_event("Hangup", handle_hangup_event)
						# SIP and IAX peers status events
						manager.register_event("PeerEntry", handle_peerentry_event)
						manager.register_event("PeerStatus", handle_peerstatus_event)
						# Agent events
						manager.register_event("Agentlogin", handle_agentlogin_event)
						manager.register_event("Agentlogoff", handle_agentlogoff_event)
						manager.register_event("Agents", handle_agents_event)

						logging.info("Sending asterisk actions")
						# Getting peers status
						manager.send_action({"Action": "SIPpeers"})
						manager.send_action({"Action": "IAXpeers"})
						manager.send_action({"Action": "Agents"})

		else:
			sys.exit(0)
	except KeyboardInterrupt:
		sys.exit(0)
	finally:
		# remember to clean up
		manager.close()

main()
